import { Dep, pushTarget, popTarget } from "../observer/dep";
import { queueWatcher } from "./scheduler";
let $number = 0;
export class Watcher {
  vm: Object;
  deps: any;
  value: any;
  getter: any;
  lazy: boolean;
  dirty: boolean;
  sync: boolean;
  id: number;
  cb: any;
  user: any;

  constructor(vm, expOrFn: Function | string, callback?, config?) {
    if (typeof expOrFn === "function") {
      this.getter = expOrFn.bind(vm);
    } else {
      this.getter = parsePath(expOrFn);
    }
    if (config) {
      this.user = !!config.user;
      this.dirty = this.lazy = !!config.lazy;
      this.sync = !!config.sync;
    } else {
      this.user = this.dirty = this.lazy = this.sync = false;
    }
    this.vm = vm;
    this.id = $number++;
    this.deps = [];
    this.value = this.dirty ? undefined : this.get();
    this.cb = callback;
  }
  get() {
    pushTarget(this);
    let value = this.getter(this.vm);
    popTarget();
    return value;
  }
  update() {
    if (this.lazy) {
      this.dirty = true;
      console.log(
        `%c ------------------计算Watcher运行----------------------`,
        "border:1px solid #ccc; border-radius:1px;padding:20px;background-color: black;color:white"
      );
    } else if (this.sync) {
      this.run();
    } else {
      queueWatcher(this);
    }
    // this.run();
  }
  addDep(dep: Dep) {
    if (!this.deps.includes(dep)) {
      this.deps.push(dep);
      dep.addSub(this);
    }
  }
  evaluate() {
    this.value = this.get();
    this.dirty = false;
  }
  depend() {
    let i = this.deps.length;
    console.log(this);
    while (i--) {
      this.deps[i].depend();
    }
  }
  run() {
    if (this.user) {
      let val = this.get();
      let oldVal = this.value;
      this.cb.call(this.vm, val, oldVal);
      this.value = val;
    } else {
      this.get();
    }
  }
}

function parsePath(path: string) {
  let pathSplit = path.split(".");
  return function (vm) {
    let val;
    pathSplit.forEach((key) => {
      val = val ? val[key] : vm[key];
    });
    return val;
  };
}
